package com.nn.algorithm;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.math3.linear.MatrixUtils;
import org.apache.commons.math3.linear.RealMatrix;

public class Persistence {

	public static RealMatrix readMatrix(int layer) {
		RealMatrix resultMatrix = null;
		double[][] matrix = null;
		int rows = 0;
		int columns = 0;
		BufferedReader in = null;
		try {
			String filepath = layer+".txt";
			int row = 0;
			in = new BufferedReader(new FileReader(filepath));
			String line = null;
			if ((line = in.readLine()) != null) {
				String[] rocol = line.split(" ");
				rows = Integer.parseInt(rocol[0]);
				columns = Integer.parseInt(rocol[1]);
				matrix = new double[rows][columns];
				while ((line = in.readLine()) != null) {
					String[] tokens = line.split(" ");
					for (int j = 0; j < tokens.length; j++) {
						matrix[row][j] = Double.parseDouble(tokens[j]);
					}
					row++;
				}
			}
			resultMatrix = MatrixUtils.createRealMatrix(matrix);
			return resultMatrix;
		} catch (Exception ex) {
			System.out.println("The code throws an exception");
			System.out.println(ex.getMessage());
		} finally {
			if (in != null)
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
		}
		return null;
	}
	
	public static void saveMatrix(int layer, RealMatrix matrix){
		PrintWriter writer;
		try {
			writer = new PrintWriter(layer+".txt");
			writer.println(matrix.getRowDimension() + " " + matrix.getColumnDimension());
			for (int i = 0; i < matrix.getRowDimension(); i++) {
				for (int j = 0; j < matrix.getColumnDimension(); j++) {
					writer.print(matrix.getEntry(i, j) + " ");
				}
				writer.println();
			}
			writer.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}

	private static void printMatrix(RealMatrix matrix) {
		for (int i = 0; i < matrix.getRowDimension(); i++) {
			for (int j = 0; j < matrix.getColumnDimension(); j++) {
				System.out.print(matrix.getEntry(i, j) + " ");
			}
			System.out.println(" ");
		}
	}
	
	private static void printMatrix(double[][] matrix, int rows, int columns) {
		for (int i = 0; i < rows; i++) {
			for (int j = 0; j < columns; j++) {
				System.out.print(matrix[i][j] + " ");
			}
			System.out.println(" ");
		}
	}
	
	public static void printVector(double[] vector, int columns) {
		for (int j = 0; j < columns; j++) {
			System.out.print(vector[j] + " ");
		}
		System.out.println(" ");
	}
	
	public static double[][] readInput(String file) {

		BufferedReader in = null;

		int lines = 0;
		int columns = 0;
		try {
			
			in = new BufferedReader(new FileReader(file));
			ArrayList<List<Double>> superList = new ArrayList<>();
			String line = null;
			while ((line = in.readLine()) != null) {
				ArrayList<Double> list = new ArrayList<>();
				String[] tokens = line.split(" ");
				for (int j = 0; j < tokens.length; j++) {
					list.add(Double.valueOf(tokens[j]));
				}
				columns = list.size();
				superList.add(list);
			}
			
			double[][] output = new double[superList.size()][columns];
			int i=0;
			for(List<Double> doubleList: superList)
			{
				int j=0;
				for(Double d: doubleList)
				{
					output[i][j]=d.doubleValue();
					j++;
				}
				i++;
			}
			return output;
			
		} catch (Exception ex) {
			System.out.println("The code throws an exception");
			ex.printStackTrace();
		} finally {
			if (in != null)
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
		}
		return null;
	}
	
	//doesn't work well
	public static double[] normalizeInputVector(double[] input){
		double[] output = new double[input.length];
		double alpha = 0.5;
		
		double x[] = new double[input.length/3];
		double y[] = new double[input.length/3];
		double z[] = new double[input.length/3];
		
		
		int j=0;
		for(int i=0; i<input.length/3; i++)
		{
			x[i] = input[i*3];
			y[i] = input[i*3+1];
			z[i] = input[i*3+2];
			j++;
		}
		
		double x_out[] = new double[input.length/3];
		double y_out[] = new double[input.length/3];
		double z_out[] = new double[input.length/3];
		
		x_out[0] = x[0];
		y_out[0] = y[0];
		z_out[0] = z[0];
		
		for(int i=1; i<input.length/3; i++)
		{
			x_out[i] = alpha * x_out[i-1] + alpha * (x[i] - x[i-1]);
			y_out[i] = alpha * y_out[i-1] + alpha * (y[i] - y[i-1]);
			z_out[i] = alpha * z_out[i-1] + alpha * (z[i] - z[i-1]);
		}
		
		for(int i=0; i<input.length/3; i++)
		{
			output[i] = x_out[i];
			output[i+1] = y_out[i];
			output[i+2] = z_out[i];
		}
		
		return output;
	}
	
	
	
	public static double[][] generateIdealOutput(int length, int type) {
		double[][] output = new double[length][3];
		for (int i = 0; i < length; i++) {
			if (type == 0) {
				output[i] = new double[] { 1, 0, 0 };
			}
			if (type == 1) {
				output[i] = new double[] { 0, 1, 0 };
			}
			if (type == 2) {
				output[i] = new double[] { 0, 0, 1 };
			}
		}
		return output;
	}

	public static void main(String[] args) {
		double XOR_INPUT[][] = { 
				{ 0.0, 0.0 }, 
				{ 1.0, 0.0 }, 
				{ 0.0, 1.0 }, 
				{ 1.0, 1.0 } };
		RealMatrix matrix = MatrixUtils.createRealMatrix(XOR_INPUT);
		Persistence.printMatrix(matrix);
		Persistence.saveMatrix(0, matrix);
		RealMatrix matrix2 = Persistence.readMatrix(0);
		Persistence.printMatrix(matrix2);
		
		double[][] input = Persistence.readInput("Running.txt");
		Persistence.printMatrix(input, 1, 72);
/*		double[][] output = Persistence.generateIdealOutput(input.length, 1);
		Persistence.printMatrix(output, 3, 3);*/
		
		double[] outputVector = Persistence.normalizeInputVector(input[0]);
		Persistence.printVector(outputVector, 72);
	}

}
